package com.xy.bizportdemo.controller;

import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Build;
import android.os.Environment;
import android.util.Log;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import dalvik.system.DexClassLoader;

/**
 * Created by admin on 2017/9/30 0030.
 */

public class PluginManager {
    private static final String TAG = "PluginManager";
    private Context mRemoteContext = null;

    private void replaceResources(Context context, Resources resources) {
        try {
            Field field = context.getClass().getDeclaredField("mResources");
            field.setAccessible(true);
            field.set(context, resources);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void replaceClassLoader(Context context, ClassLoader classLoader) {
        Object object = context;
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
            try {
                Field field = context.getClass().getDeclaredField("mPackageInfo");
                field.setAccessible(true);
                object = field.get(context);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        replaceClassLoader(object, classLoader);
    }

    private void replaceClassLoader(Object object, ClassLoader classLoader) {
        try {
            Field field = object.getClass().getDeclaredField("mClassLoader");
            field.setAccessible(true);
            field.set(object, classLoader);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void addAssetPath(Context context, String resourceFile) {
        try {
            AssetManager assetManager = context.getAssets();
            Method addAssetPath = assetManager.getClass().getDeclaredMethod("addAssetPath", String.class);
            addAssetPath.invoke(assetManager, resourceFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private AssetManager createAssetManager(String resourceFile) {
        try {
            AssetManager assetManager = AssetManager.class.newInstance();
            Method addAssetPath = assetManager.getClass().getDeclaredMethod("addAssetPath", String.class);
            addAssetPath.invoke(assetManager, resourceFile);
            return assetManager;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public Context getPluginContext() {
        Log.i(TAG, "getPluginContext: remote context=" + mRemoteContext + mRemoteContext.hashCode());
        return mRemoteContext;
    }

    private void testAsset(Context context, String filename) {
        InputStream is = null;
        try {
            is = context.getResources().getAssets().open(filename);
            Log.i(TAG, "testAsset: is=" + is + filename);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {

                }
            }
        }

    }

    public Object loadSMSProcessor(Context context) {
        try {
            Log.i(TAG, "loadSMSProcessor: local context=" + context + context.hashCode());

            String cachePath = context.getCacheDir().getAbsolutePath();
            String apkPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download/plugin.zip";

            //addAssetPath(context, apkPath);
            testAsset(context, "duoqu_parse_version.txt");
            Log.i(TAG, "loadSMSProcessor: cachePath=" + cachePath);
            Log.i(TAG, "loadSMSProcessor: apkPath=" + apkPath);
            DexClassLoader loader = new DexClassLoader(apkPath, cachePath, cachePath, context.getClassLoader());
            AssetManager assetManager = createAssetManager(apkPath);
            Log.i(TAG, "loadSMSProcessor: assetManager =" + context.getAssets());
            Log.i(TAG, "loadSMSProcessor: assetManager new =" + assetManager);
            Resources resources = new Resources(assetManager, context.getResources().getDisplayMetrics(), context.getResources().getConfiguration());
            mRemoteContext = context.createConfigurationContext(resources.getConfiguration());
            replaceResources(mRemoteContext, resources);
            replaceClassLoader(mRemoteContext, loader);
            testAsset(mRemoteContext, "duoqu_parse_version.txt");
            return loader.loadClass("com.xy.smartsms.adapter.XySmartSMSProcessor").newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private static PluginManager sManager = null;

    public static PluginManager getInstance() {
        if (sManager == null) {
            synchronized (PluginManager.class) {
                if (sManager == null) {
                    sManager = new PluginManager();
                }
            }
        }

        return sManager;
    }
}
